<template>
    <view class="container">
      <view class="map-wrapper" ref="mapWrapper" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
        <view class="map-content" :style="transformStyle">
          <svg :width="displayWidth" :height="displayHeight" style="background: transparent;">
            <!-- SVG渐变定义 -->
            <defs>
              <!-- 机器人渐变 -->
              <radialGradient id="robotGradient" cx="50%" cy="30%" r="70%">
                <stop offset="0%" style="stop-color:#00ff88;stop-opacity:1" />
                <stop offset="70%" style="stop-color:#00cc66;stop-opacity:0.8" />
                <stop offset="100%" style="stop-color:#008844;stop-opacity:0.6" />
              </radialGradient>
              
              <!-- 轨迹渐变 -->
              <linearGradient id="trajectoryGradient" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" style="stop-color:#00d4ff;stop-opacity:0.8" />
                <stop offset="50%" style="stop-color:#0099cc;stop-opacity:1" />
                <stop offset="100%" style="stop-color:#00d4ff;stop-opacity:0.8" />
              </linearGradient>
            </defs>
  
            <!-- 使用transform实现垂直翻转 -->
            <g :transform="`scale(1, -1) translate(0, ${-displayHeight})`">
              <!-- 地图栅格 -->
              <template v-if="mapData && mapData.length > 0">
                <g>
                  <rect v-for="(chunk, chunkIndex) in mapChunks" :key="'chunk-'+chunkIndex" :x="chunk.x"
                    :y="chunk.y" :width="chunk.width" :height="chunk.height"
                    :class="['cell', chunk.class]" :style="chunk.style" />
                </g>
              </template>
              <text v-else x="400" y="-300" class="waiting-text" transform="scale(1, -1)">⏳ 等待地图数据...</text>
  
              <!-- 激光扫描线 -->
              <g v-if="showLaserPoints && laserPoints.length > 0">
                <path :d="laserLinesPath" class="laser-line" />
                <path :d="laserPointsPath" class="laser-point" />
              </g>
  
              <!-- 机器人位置 -->
              <g v-if="robotPosition.x !== undefined && robotPosition.y !== undefined" 
                 :transform="getRobotTransform() + ` scale(1, -1)`">
                <circle class="robot" r="6" />
                <line class="robot-direction" x1="0" y1="0"
                  :x2="8 * Math.cos(-robotPosition.yaw * Math.PI / 180)"
                  :y2="8 * Math.sin(-robotPosition.yaw * Math.PI / 180)" />
              </g>
            </g>
          </svg>
        </view>
      </view>
      
    </view>
  </template>
  
  <script>
  import * as mqttService from '@/utils/mqttService.js';
  
  export default {
    data() {
      return {
        width: 0,
        height: 0,
        displayWidth: 800,  // 默认显示尺寸
        displayHeight: 600, // 默认显示尺寸
        resolution: 0,
        mapData: [],
        cellSize: 1,
        currentScale: 1,  // 初始缩放比例设为1
        currentX: 0,
        currentY: 0,
        isPanning: false,
        lastX: 0,
        lastY: 0,
        initialScale: 1,  // 初始缩放比例
        robotPosition: {
          x: 0,
          y: 0,
          yaw: 0,
          power: 0,
          velocity: { vx: 0, vy: 0, vz: 0 }
        },
        laserPoints: [],
        showLaserPoints: false,
        // 地图原点和坐标转换参数
        mapOriginX: 0,
        mapOriginY: 0,
        mapOriginYaw: 0,
        displayScale: 5
      }
    },
    computed: {
      // 地图数据分块处理
      mapChunks() {
        if (!this.mapData || !this.width) return [];
  
        const chunks = [];
        const CHUNK_SIZE = 10; // 每个块的大小
  
        for (let y = 0; y < this.height; y += CHUNK_SIZE) {
          for (let x = 0; x < this.width; x += CHUNK_SIZE) {
            const chunkWidth = Math.min(CHUNK_SIZE, this.width - x);
            const chunkHeight = Math.min(CHUNK_SIZE, this.height - y);
  
            // 检查这个块中的所有单元格
            let allSame = true;
            const firstValue = this.mapData[y * this.width + x];
            const firstClass = this.getCellClass(firstValue);
            const firstStyle = this.getCellStyle(firstValue);
  
            for (let dy = 0; dy < chunkHeight && allSame; dy++) {
              for (let dx = 0; dx < chunkWidth && allSame; dx++) {
                const index = (y + dy) * this.width + (x + dx);
                if (this.getCellClass(this.mapData[index]) !== firstClass) {
                  allSame = false;
                }
              }
            }
  
            if (allSame) {
              chunks.push({
                x: this.getX(y * this.width + x),
                y: this.getY(y * this.width + x),
                width: chunkWidth,
                height: chunkHeight,
                class: firstClass,
                style: firstStyle
              });
            } else {
              // 如果不是所有单元格都相同，则单独处理每个单元格
              for (let dy = 0; dy < chunkHeight; dy++) {
                for (let dx = 0; dx < chunkWidth; dx++) {
                  const index = (y + dy) * this.width + (x + dx);
                  chunks.push({
                    x: this.getX(index),
                    y: this.getY(index),
                    width: 1,
                    height: 1,
                    class: this.getCellClass(this.mapData[index]),
                    style: this.getCellStyle(this.mapData[index])
                  });
                }
              }
            }
          }
        }
        return chunks;
      },
  
      // 激光线路径优化
      laserLinesPath() {
        if (!this.showLaserPoints || !this.laserPoints.length) return '';
        return this.laserPoints.map(point =>
          `M${this.robotPosition.x},${this.robotPosition.y} L${point.x},${point.y}`
        ).join(' ');
      },
  
      // 激光点路径优化
      laserPointsPath() {
        if (!this.showLaserPoints || !this.laserPoints.length) return '';
        return this.laserPoints.map(point =>
          `M${point.x},${point.y} m-1,0 a1,1 0 1,0 2,0 a1,1 0 1,0 -2,0`
        ).join(' ');
      },
  
      transformStyle() {
        return {
          transform: `scale(${this.currentScale}) translate(${this.currentX}px, ${this.currentY}px)`,
          transformOrigin: 'center'
        };
      }
    },
    methods: {
      // 坐标转换方法
      getX(index) {
        if (!this.width) return 0;
        const x = index % this.width;
        const offset = (this.displayWidth - this.width) / 2;
        return Math.floor(x + offset);
      },
      getY(index) {
        if (!this.width) return 0;
        const y = Math.floor(index / this.width);
        const offset = (this.displayHeight - this.height) / 2;
        return Math.floor(y + offset);
      },
  
      // 将地图坐标转换为显示坐标
      mapToDisplay(mapX, mapY) {
        // 转换为像素坐标
        const pixelX = (mapX - this.mapOriginX) / this.resolution;
        const pixelY = (mapY - this.mapOriginY) / this.resolution;
        
        // 调整到显示坐标系
        const displayX = pixelX + (this.displayWidth - this.width) / 2;
        const displayY = pixelY + (this.displayHeight - this.height) / 2;
        
        return [displayX, displayY];
      },
  
      // 机器人位置转换
      getRobotTransform() {
        return `translate(${this.robotPosition.x}, ${this.robotPosition.y})`;
      },
  
      // 获取单元格类型
      getCellClass(value) {
        if (value === -1) return 'unknown';
        return value > 50 ? 'occupied' : 'free';
      },
  
      // 获取单元格样式
      getCellStyle(value) {
        if (value === -1) return {};
        const intensity = Math.min(100, Math.max(0, value)) / 100;
        const hue = 48;
        const sat = 100;
        const light = 10 + intensity * 40; // 10%~50%亮度，越大越黄
        if (value === 0) {
          return { fill: '#080b1a' };
        } else {
          return {
            fill: `hsl(${hue}, ${sat}%, ${light}%)`
          };
        }
      },
  
      // 显示设置
      zoomIn() {
        this.currentScale = Math.min(this.currentScale * 1.2, 10);
        this.calculateMapPosition();
      },
      zoomOut() {
        this.currentScale = Math.max(this.currentScale / 1.2, 0.2);
        this.calculateMapPosition();
      },
      resetZoom() {
        this.currentScale = 1;
        this.calculateMapPosition();
      },
      toggleLaserPoints(e) {
        this.showLaserPoints = e.detail.value;
      },
      calculateMapPosition() {
        if (this.width && this.height) {
          const wrapper = this.$refs.mapWrapper;
          if (wrapper) {
            const containerWidth = wrapper.offsetWidth || this.displayWidth;
            const containerHeight = wrapper.offsetHeight || this.displayHeight;
  
            // 计算地图在当前缩放比例下的实际尺寸
            const mapWidth = this.width;
            const mapHeight = this.height;
  
            // 计算居中位置（考虑缩放）
            this.currentX = (containerWidth / this.currentScale - mapWidth) / 2;
            this.currentY = (containerHeight / this.currentScale - mapHeight) / 2;
          }
        }
      },
  
      // 触摸事件处理
      handleTouchStart(e) {
        const touch = e.touches[0];
        this.isPanning = true;
        this.lastX = touch.clientX;
        this.lastY = touch.clientY;
      },
      handleTouchMove(e) {
        if (!this.isPanning) return;
        const touch = e.touches[0];
        const dx = (touch.clientX - this.lastX);
        const dy = (touch.clientY - this.lastY);
        this.currentX += dx;
        this.currentY += dy;
        this.lastX = touch.clientX;
        this.lastY = touch.clientY;
      },
      handleTouchEnd() {
        this.isPanning = false;
      },
  
      // 处理激光扫描数据
      processLaserScan(scanData) {
        if (!scanData) return [];
        
        // 获取激光雷达参数
        const angleMin = scanData.hed[0];  // 开始扫描的角度
        const angleIncrement = scanData.hed[2];  // 每次扫描增加的角度
        const ranges = scanData.ranges;  // 距离数据
        const scanPose = scanData.pose;  // 激光雷达位置
        
        const laserPoints = [];
        // 每隔8个点取一个，减少数据量
        for (let i = 0; i < ranges.length; i += 8) {
          const r = ranges[i];
          // 跳过无效数据（距离小于0.1米）
          if (r <= 0.1) continue;
            
          // 计算当前激光点的角度（注意这里是2*i）
          const angle = angleMin + 2 * i * angleIncrement;
          
          // 计算激光点在激光雷达坐标系中的位置
          const pointX = r * Math.cos(angle);
          const pointY = r * Math.sin(angle);
          
          // 转换到世界坐标系
          const worldX = pointX * Math.cos(scanPose.yaw) - pointY * Math.sin(scanPose.yaw) + scanPose.x;
          const worldY = pointX * Math.sin(scanPose.yaw) + pointY * Math.cos(scanPose.yaw) + scanPose.y;
          
          // 转换到显示坐标系
          const [displayX, displayY] = this.mapToDisplay(worldX, worldY);
          laserPoints.push({ x: displayX, y: displayY });
        }
        
        return laserPoints;
      },
  
      // MQTT数据处理
      setupMqtt() {
        // 连接MQTT
        mqttService.connectMqtt();
        
        // 订阅地图数据
        mqttService.subscribe('map', (topic, message) => {
          try {
			  console.log(message)
            const data = JSON.parse(message.toString());
            if (data.cmd_type === 'map') {
              this.handleMapData(data);
            }
          } catch (error) {
            console.error('解析地图数据失败', error);
          }
        });
        
        // 订阅激光扫描数据
        mqttService.subscribe('scan', (topic, message) => {
          try {
            const data = JSON.parse(message.toString());
            if (data.cmd_type === 'scan') {
              this.laserPoints = this.processLaserScan(data);
            }
          } catch (error) {
            console.error('解析激光数据失败', error);
          }
        });
        
        // 订阅机器人位置数据
        mqttService.subscribe('base_status', (topic, message) => {
          try {
            const data = JSON.parse(message.toString());
            if (data.cmd_type === 'base_status') {
              this.handleRobotData(data);
            }
          } catch (error) {
            console.error('解析机器人数据失败', error);
          }
        });
      },
  
      // 请求地图数据
      requestMap() {
        const mapRequest = {
          cmd_type: 'slam_map_control',
          cmd: 'get'
        };
        
        mqttService.publishMessage('robot_control', JSON.stringify(mapRequest));
        uni.showToast({
          title: '已请求地图数据',
          icon: 'none'
        });
      },
  
      // 处理地图数据
      handleMapData(data) {
        console.log('接收到地图数据');
        
        // 提取地图基本信息
        const width = data.width;
        const height = data.height;
        const resolution = data.resolution;
        const originX = data.pose.x;
        const originY = data.pose.y;
        const originYaw = data.pose.yaw;
        const mapData = data.data;
        const mode = data.mode || 0;
  
        // 更新坐标转换参数
        this.width = width;
        this.height = height;
        this.resolution = resolution;
        this.mapOriginX = originX;
        this.mapOriginY = originY;
        this.mapOriginYaw = originYaw;
        this.displayWidth = width * this.displayScale;
        this.displayHeight = height * this.displayScale;
  
        // 处理地图数据
        let occupancy = [];
        if (mode === 1) {  // 建图模式
          let idx = 0;
          for (const byte of mapData) {
            for (let bit = 0; bit < 8; bit++) {
              if (idx >= width * height) break;
              const value = (byte & (1 << bit)) ? 0 : 100;
              occupancy.push(value);
              idx++;
            }
          }
        } else {  // 非建图模式
          occupancy = mapData;
        }
  
        // 更新地图数据
        this.mapData = occupancy.slice(0, width * height);
        console.log(`地图更新: ${width}x${height}, 单元格数量: ${this.mapData.length}`);
        
        // 重新计算位置
        this.$nextTick(() => {
          this.calculateMapPosition();
        });
      },
  
      // 处理机器人位置数据
      handleRobotData(data) {
        const pose = data.pose || {};
        const robot = data.robot || {};
        
        // 转换机器人位置到显示坐标系
        const [robotX, robotY] = this.mapToDisplay(pose.x || 0, pose.y || 0);
        
        // 更新机器人位置
        this.robotPosition = {
          x: robotX,
          y: robotY,
          yaw: (pose.yaw || 0) * 57.3,  // 转换为角度
          power: robot.power || 0,
          velocity: {
            vx: robot.vx || 0,
            vy: robot.vy || 0,
            vz: robot.vz || 0
          }
        };
      }
    },
    onLoad() {
      // 设置初始状态
      this.setupMqtt();
      
      // 请求地图数据
      setTimeout(() => {
        this.requestMap();
      }, 1000);
    },
    onUnload() {
      // 组件销毁时取消订阅
      mqttService.unsubscribe('map');
      mqttService.unsubscribe('scan');
      mqttService.unsubscribe('base_status');
    }
  }
  </script>
  
  <style>
  .container {
    display: flex;
    flex-direction: column;
    height: 100vh;
    background: linear-gradient(135deg, #0a0f1c 0%, #1a1a2e 50%, #16213e 100%);
    padding: 10px;
  }
  
  .map-wrapper {
    position: relative;
    flex: 1;
    background: rgba(5, 10, 25, 0.95);
    border: 1px solid rgba(0, 212, 255, 0.3);
    border-radius: 8px;
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  }
  
  .map-content {
    transform-origin: center;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .controls {
    display: flex;
    padding: 10px 0;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
  }
  
  .tech-button {
    padding: 8px 16px;
    border: none;
    border-radius: 8px;
    background: linear-gradient(135deg, rgba(0, 212, 255, 0.2), rgba(0, 212, 255, 0.1));
    color: #00d4ff;
    border: 1px solid #00d4ff;
    font-size: 14px;
  }
  
  .switch-label {
    display: flex;
    align-items: center;
    color: #00d4ff;
  }
  
  /* SVG样式 */
  .cell {
    stroke: none;
  }
  
  .occupied {
    fill: #1a1b3e;
  }
  
  .free {
    fill: #060815;
  }
  
  .unknown {
    fill: #101220;
    opacity: 0.8;
  }
  
  .robot {
    fill: url(#robotGradient);
    stroke: #00ff88;
    stroke-width: 2;
  }
  
  .robot-direction {
    stroke: #00ff88;
    stroke-width: 3;
    stroke-linecap: round;
  }
  
  .laser-line {
    stroke: rgba(235, 102, 45, 1);
    stroke-width: 0.1;
    stroke-linecap: round;
  }
  
  .laser-point {
    fill: #ee2b2b;
    r: 1;
  }
  
  .waiting-text {
    fill: #00d4ff;
    font-size: 16px;
    text-anchor: middle;
  }
  </style>